package rtcf.framework
{

	import flash.net.NetConnection;
	import flash.net.Responder;
	import flash.net.SharedObject;
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;
	
	use namespace flash_proxy;

	public dynamic class RTCFComponent extends Proxy
	{
	
		private var _remoteMethodProxies:Object = {};
		private var _rmiID_:String;
		private var _nc_:NetConnection;
		public var _resourcePath_:String;
		public var _fullResourcePath_:String;
		public var rtcfApplication:RTCFApplication;
		public var config:XML;
		
		public function RTCFComponent(rmiID:String)
		{
			super();
			_rmiID_ = rmiID;
			
		}
		
		public function set nc(netConnection:NetConnection):void{
			_nc_ = netConnection;
		}
		
		public function getStream(peerID:String="connectToFMS"):RTCFStream{
			var stream:RTCFStream = new RTCFStream(this, rtcfApplication.rtcfConnection, peerID);
			return stream;
		}
		
		public function getSharedObject(name:String, persistence:Object = false, secure:Boolean = false):RTCFSharedObject{
			
			if (!rtcfApplication){
				trace("getSharedObject> ERROR! No RTCFApplication!");
				return null;
			}
			
			_nc_ = rtcfApplication.rtcfConnection;
			_resourcePath_ = config.@resourcePath; 
			trace("RESOURCE: " + _resourcePath_);
			_fullResourcePath_ = "rtcfResources/" + _resourcePath_;
			trace("FULL " + _fullResourcePath_);
			if (! _resourcePath_){
				trace("ERROR! RTCFComponent.getSharedObject. Cannot get a shared object without a resource path." );
				return null;	
			}
			if (! _nc_){
				trace("ERROR! RTCFComponent.getSharedObject. Cannot get a shared object without a net connection.");
				return null;
			}
			name = _fullResourcePath_ + name;
			trace("shared object name: " + name);
			// return SharedObject.getRemote(name, _nc_.uri, persistence, secure);	
			return new RTCFSharedObject(SharedObject.getRemote(name, _nc_.uri, persistence, secure), _nc_);	
		}
		
		public function connectSharedObject(so:SharedObject):void{
			if (!rtcfApplication){
				trace("connectSharedObject> ERROR! No RTCFApplication!");
				return;
			}
			trace("typeof so: " + typeof so);
			so.connect(rtcfApplication.rtcfConnection);
			return;
		}
		
		public function call(command:String, responder:Responder, ... args):void{
			_nc_ = rtcfApplication.rtcfConnection;
			if (! _nc_){
				trace("call> ERROR! Can't call remote method. NetConnection is null.");
				return;
			}
			
			trace("Compose RMI Name from _rmiID_ and command: " + _rmiID_ + ", " + command);
			args.unshift(command);
			args.unshift(_rmiID_);
			args.unshift(responder);
			args.unshift("c2s");
			
			_nc_.call.apply(_nc_, args);
		}
			
			
		
		
    //// ---- ---- Proxy methods ---- ---- ////
    
    /**
     * 
     */
    override flash_proxy function getProperty(name:*):*
    {

        if (! _remoteMethodProxies[name]){
        	_remoteMethodProxies[name] = new RemoteMethodProxy();
        }
        return _remoteMethodProxies[name];
    }

    /**
     *
     */
    override flash_proxy function setProperty(name:*, value:*):void
    {
    	trace("RTCFComponent.setProperty is not implemented yet!");
        trace("setProperty(" + name + ", " +  value + ")");
        return ;
    }

    /**
     *
     */
    override flash_proxy function callProperty(name:*, ... args:Array):*
    {
		_nc_ = rtcfApplication.rtcfConnection;
        if (! _remoteMethodProxies[name]){
        	_remoteMethodProxies[name] = new RemoteMethodProxy();
        }
		
		var rm:RemoteMethodProxy = _remoteMethodProxies[name];
		var params:Array = ["c2s", rm.responder, this._rmiID_, name.toString()];  
		for (var i:int = 0; i < args.length; i++)  params.push(args[i]);   
		_nc_.call.apply(_nc_, params);
		
        return null;
    }

    //used to store the nextName values
    private var nextNameArray:Array;
    
    
    /**
     * 
     */
    override flash_proxy function nextNameIndex(index:int):int
    {/*
        if (index == 0)
        {
            nextNameArray = [];
            for (var op:String in _operations)
            {
                nextNameArray.push(op);    
            }    
        }
        return index < nextNameArray.length ? index + 1 : 0;
        */
        return 0;
    }

    /**
     * 
     */
    override flash_proxy function nextName(index:int):String
    {
    	/*
        return nextNameArray[index-1];
        */
        return 'hi';
    }

    /**
     * 
     */
    override flash_proxy function nextValue(index:int):*
    {
       //return _operations[nextNameArray[index-1]];
       return null;
    }

    private function getLocalName(name:Object):String
    {
    	/*
        if (name is QName)
        {
            return QName(name).localName;
        }
        else
        {
            return String(name);
        }
        */
        return null;
    }
	
	}
}